package com.zmkj.cn.comm.plugin;


import com.zmkj.cn.comm.constant.SpecialFieldsConstant;
import com.zmkj.cn.sys.dto.SysManagerDto;
import com.zmkj.cn.comm.util.ThreadLocalUtil;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.Properties;


@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class SaveMapperPlugin implements Interceptor {


    /**
     * 拦截时执行的操作
     *
     * @param invocation { 代理对象，被监控方法对象，当前被监控方法运行时需要的实参 }
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        // 获取 SQL 命令
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        // 获取参数
        Object parameter = invocation.getArgs()[1];
        if (parameter != null) {
            // 获取成员变量
            Field[] declaredFields = parameter.getClass().getDeclaredFields();
            for (Field field : declaredFields) {
                createSaveTime(sqlCommandType, parameter, field);
                createUpdateTime(sqlCommandType, parameter, field);
                createSaveUser(sqlCommandType, parameter, field);
                createUpdateUser(sqlCommandType, parameter, field);
                createDeptNo(sqlCommandType, parameter, field);
            }
        }
        Object obj = invocation.proceed();
        return obj;
    }

    private void createDeptNo(SqlCommandType sqlCommandType, Object parameter, Field field) throws IllegalAccessException {
        if (field.getName() == SpecialFieldsConstant.DEPTNO.code) {
            // insert 语句插入 updateTime
            if (SqlCommandType.INSERT.equals(sqlCommandType)) {
                field.setAccessible(true);
                if (field.get(parameter) == null) {
                    field.set(parameter, ThreadLocalUtil.getCurrentManager().getDeptNo());
                }
            }
        }
    }

    private void createUpdateUser(SqlCommandType sqlCommandType, Object parameter, Field field) throws IllegalAccessException {
        if (field.getName() == SpecialFieldsConstant.UPDATEUSER.code) {
            // insert 语句插入 updateTime
            if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
                field.setAccessible(true);
                if (field.get(parameter) == null) {
                    createUserInfo(parameter, field);
                }
            }
        }
    }

    private void createUserInfo(Object parameter, Field field) throws IllegalAccessException {
        SysManagerDto sysManagerDto = ThreadLocalUtil.getCurrentManagerWithNoCheck();
        if (sysManagerDto != null) {
            field.set(parameter, sysManagerDto.getId() + "");
        } else {
            field.set(parameter, 0 + "");
        }
    }

    private void createSaveUser(SqlCommandType sqlCommandType, Object parameter, Field field) throws IllegalAccessException {
        if (field.getName() == SpecialFieldsConstant.CREATEUSER.code) {
            // insert 语句插入 updateTime
            if (SqlCommandType.INSERT.equals(sqlCommandType)) {
                field.setAccessible(true);
                if (field.get(parameter) == null) {
                    createUserInfo(parameter, field);
                }
            }
        }
    }


    /**
     * 组装修改时间
     *
     * @param sqlCommandType
     * @param parameter
     * @param field
     * @throws IllegalAccessException
     */
    private void createUpdateTime(SqlCommandType sqlCommandType, Object parameter, Field field) throws IllegalAccessException {
        if (field.getName() == SpecialFieldsConstant.UPDATETIME.code) {
            // insert 语句插入 updateTime
            if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
                field.setAccessible(true);
                if (field.get(parameter) == null) {
                    field.set(parameter, new Date());
                }
            }
        }
    }

    /**
     * 组装新增时间
     *
     * @param sqlCommandType
     * @param parameter
     * @param field
     * @throws IllegalAccessException
     */
    private void createSaveTime(SqlCommandType sqlCommandType, Object parameter, Field field) throws IllegalAccessException {
        if (field.getName().equals(SpecialFieldsConstant.CREATETIME.code)) {
            // insert 语句插入 createTime
            if (SqlCommandType.INSERT.equals(sqlCommandType)) {
                field.setAccessible(true);
                if (field.get(parameter) == null) {
                    field.set(parameter, new Date());
                }
            }
        }
    }


    /**
     * 拦截器用于封装目标对象的
     * 通过该方法我们可以返回目标对象本身，也可以返回一个它的代理
     *
     * @param o
     * 
     */
    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }

    /**
     * 用于在 Mybatis 配置文件中指定一些属性的。
     *
     * @param properties
     */
    @Override
    public void setProperties(Properties properties) {

    }


}
